<?php

/**
 *      [Discuz!] (C)2001-2099 Comsenz Inc.
 *      This is NOT a freeware, use is subject to license terms
 *
 *      $Id: dzf_memory_cmem.php 1942 2013-08-27 09:24:19Z andyzheng $
 */

class dzf_memory_cmem
{
	public $handler;
	public $bid;
	public $enable;
	/**
	 * 最大长度
	 */
	const MAX_LENGTH = 10485760;
	/**
	 * _errorMessages
	 * 错误信息列表
	 *
	 * 11001 = '连接超时',
	 * 11002 = '接入机/库ID配置错误',
	 * 11006 = 'TMEM不可服务，联系运维',
	 * 11007 = '参数非法，检查参数',
	 * 11008 = '接入机队列饱和',
	 * 11009 = '一次批量获取节点数过多',
	 * 11010 = '一次批量更新节点数过多',
	 * 11011 = '一次批量删除节点数过多',
	 * 11012 = '拒绝访问，联系运维检查',
	 * 11900 = '参数非法，检查参数',
	 * 11901 = '编码错误',
	 * 11902 = '接受包异常',
	 * 11903 = '收到非TMEM协议包',
	 * 11904 = '收到非法包',
	 * 11905 = '连接出错',
	 * 11906 = '发送出错',
	 * 11907 = '接收错误',
	 * 11908 = '消息乱序',
	 * 11909 = '单次发包过大',
	 * 11910 = '列号不合法，0~511',
	 * 11911 = '空请求',
	 * 11912 = '发送的节点数和返回的节点数对不上',
	 * 11913 = '参数不合法，检查参数',
	 * 11914 = '批量太长',
	 * 11915 = '读请求超时',
	 * 13000 = '非法消息',
	 * 13001 = '管道满了',
	 * 13002 = '偏移操作参数不合法',
	 * 13003 = '二进制加操作不合法',
	 * 13004 = '列操作不合法',
	 * 13005 = 'cache不支持列',
	 * 13006 = '非法master',
	 * 13103 = 'cache版本错误',
	 * 13104 = 'CAS错误',
	 * 13105 = 'del操作，key不存在',
	 * 13106 = 'get操作，key过期',
	 * 13109 = 'add操作，key已存在',
	 * 13200 = 'get操作，key不存在',
	 * 13205 = '数据存满，须扩容',
	 *
	 * @var array
	 */
	private static $_errorMessages = array(
		11001 => 'Time out.',
		11002 => 'Host/Port or Bid was invalid.',
		11006 => 'TMEM is gone.',
		11007 => 'The params is illegal.',
		11008 => 'Access timer is error.',
		11009 => 'Access get list too big.',
		11010 => 'Access set list too big.',
		11011 => 'Access del list too big.',
		11012 => 'Strategy deny.',
		11900 => 'The params is illegal.',
		11901 => 'Encode is error.',
		11902 => 'Decode is error.',
		11903 => 'Pkt is error.',
		11904 => 'Choice is error.',
		11905 => 'Connect is error.',
		11906 => 'Send is error.',
		11907 => 'Receive is error.',
		11908 => 'Seq not match.',
		11909 => 'Pack is too big.',
		11910 => 'Col is invalid.',
		11911 => 'Empty request.',
		11912 => 'Trans not match.',
		11913 => 'The params is illegal.',
		11914 => 'List too long.',
		11915 => 'Read time out.',
		13000 => 'MSG is illegal.',
		13001 => 'PIPE is full.',
		13002 => 'PARSE args is illegal.',
		13003 => 'ADD parse args is illegal.',
		13004 => 'SO parse args is illegal.',
		13005 => 'SO parse not support.',
		13006 => 'MASTER msg is invalid.',
		13103 => 'CACHE version is error.',
		13104 => 'CAS Token was invalid or expired.',
		13105 => 'Key is not exists.',
		13106 => 'Expire is out of time.',
		13109 => 'Key is exists.',
		13200 => 'Key is not exists.',
		13205 => 'The storage is full.',
	);

	public function init($config) {
		if(!empty($config['servers'])) {
			try {
				$server = $config['servers'][rand(0, 3)];
				$this->handler = tmem_connect(array($server));

				if($this->handler) {
					$this->bid = $config['bid'];
					$this->enable = $this->handler ? true : false;
				} else {

				}
			} catch (RedisException $e) {
			}
		}
	}

	public function &instance() {
		static $object;
		if(empty($object)) {
			$object = new memory_driver_cmem();
			$object->init(getglobal('config/memory/cmem'));
		}
		return $object;
	}

	/**
	 * get
	 * 根据key获取记录
	 *
	 * @param  string $key 键值
	 * @param  integer $cas cas值，-1为不使用cas机制，引用传递
	 * @param  integer $offset 偏移位置
	 * @param  integer $len 偏移长度
	 * @return string 对应value的值
	 */
	public function get($key, $cas = -1, $offset = 0, $len = -1) {

		$result = tmem_get($this->handler, $this->bid, $key, $cas, $offset, $len);
		if($result === false) {
			$this->catchError();
			return false;
		}
		$result = ($unreturn = dunserialize($result)) ? $unreturn : $result;
		return $result;
	}

	/**
	 * set
	 * 覆盖记录
	 *
	 * @param  string $key Key
	 * @param  array $data 数据
	 * @param  integer $cas cas值，-1为不使用cas机制
	 * @param  integer $expire 有效期，0为永久
	 * @param  integer $offset 偏移位置
	 * @param  integer $len 偏移长度
	 * @return boolean
	 */
	public function set($key, $data, $expire = 0, $offset = 0, $len = -1, $cas = -1) {

		$data = serialize($data);
		if(strlen($data) > self::MAX_LENGTH) {
			throw new Exception('The data too big.', 1001);
		}

		$result = tmem_set($this->handler, $this->bid, $key, $data, $cas, $expire, $offset, $len);
		if($result === false) {
			$this->catchError();
			return false;
		}

		return true;
	}

	/**
	 * rm
	 * 删除记录
	 *
	 * @param  string $table 表名
	 * @param  string $key Key
	 * @param  integer $cas cas值，-1为不使用cas机制
	 * @return boolean
	 */
	public function rm($key, $cas = -1) {

		$result = tmem_del($this->handler, $this->bid, $key, $cas);

		if($result === false) {
			$this->catchError();
			return false;
		}

		return $result;
	}



	public function inc($key, $step = 1) {
		return false;
	}

	public function dec($key, $step = 1) {
		return false;
	}

	public function clear() {
		return false;
	}

	/*
	 * _catchError
	* 异常捕获
	*
	*/
	public function catchError() {

		$errorCode = tmem_get_last_err($this->handler);
		$errorCode = abs($errorCode);

		if ($errorCode && $errorCode != 13200 && $errorCode != 13105 && $errorCode != 13106) {
			if(self::$_errorMessages[$errorCode]) {
				$message = self::$_errorMessages[$errorCode];
			} else {
				$message = 'TMEM operation error('.$errorCode.').';
			}
			$errorMessage = sprintf('TMEM[%d] %s', $this->_bid, $message);
			throw new Exception($errorMessage, $errorCode);
		}
	}
}

?>
